[contents] [next] [bottom] (1 out of 5)

Chapter 8 - Exceptions

An exception is an unusual or abnormal situation in a script or in the ScriptX system that might cause your ScriptX program to fail. For example, you might attempt to divide a number by zero. The ScriptX exception system allows you "catch" those exceptions and handle them gracefully. So, if a "divide by zero" exception occurs, you can catch the exception, print a warning, restore your variables to their original values, and continue executing the program.

The ScriptX exception system is made up of three parts:

This chapter describes how to catch and handle single exceptions, classes of exceptions, or all exceptions in your scripts, as well as how to report (sometimes called "throw") an exception.

The core classes define a standard set of exception classes that represent common errors, warnings, or other unwanted situations that may occur during the execution of a script. In addition, you can create your own classes and instances to represent kinds of exceptions and specific exceptions that your code might report during its execution.

For more details on the core set of exception classes, see the ScriptX Class Reference. For more information on defining your own exceptions, see "Creating Exception Subclasses and Instances" on page 181.

Catching and Handling Exceptions

ScriptX provides the following guard construct, which allows you to catch and handle exceptions within your scripts:

guard
guardedCode
[ catching
exceptionName [ lexicalName ]:[ action ]
... ]
[ on exit
exitCode ]
end
The guardedCode is an expression (often a compound expression) containing the code to be guarded. Code that may report an exception must be guarded if that exception is to be caught. Any ScriptX expression can be guarded, with the following exceptions:

The optional catching section contains a tagged list of exceptions to check for, each one matched with an expression to execute if an exception occurs. This list is sometimes referred to as the catch list. Use exceptionName to specify one of three types of values: an instance of an exception class (to catch a specific exception), an exception class (to catch any exception within a class of exceptions), or the keyword all (to catch all exceptions).

Each item in the catch list can have a lexical name associated with its action. The optional lexicalName, if one is given, is bound to the argument that is reported with the exception, allowing the expression that catches and handles the exception to process this argument as well. When ScriptX reports an exception, the exception is bound to the global variable throwTag, and its reporting argument, if defined, to the global variable throwArg. These two global variables are covered in greater detail in the section "Retrieving Information about the Exception" on page 180. Think of each item in the tagged list of exceptions as being equivalent to throwTag throwArg, where throwArg is optional.

Expressions in the catch list are often compound expressions. These expressions could be used to print a message or handle some other consequence of catching the exception.

The optional on exit section contains an expression (often a compound expression) that is always executed whether or not the guarded code reports an exception. The expression in on exit is guaranteed to be executed.

Further details on each of these guard clauses are given in the remainder of this section.

caught and throw again

ScriptX also provides the caught and the throw again expressions, which, when used within the catching clause of the guard construct, prevent the remaining statements in the catch list from being executed after an exception has been caught.

The caught expression specifies that the exception has been caught. Once the exception has been caught, ScriptX immediately breaks out of the catching loop and does not check the remaining clauses in the catching clause or any other catch lists. The caught expression requires one argument, an expression containing the return value of the guard clause if that guard clause resulted in an exception. For example, if the guarded code is the generic function addMany, and the script attempts to add too many items to a collection, the argument to caught, and therefore the return value of guard, might be an error message:

global myArray := new Array initialSize:10 growable:false
global otherArray := #(1,2,3,4,5,6,7,8,9,10,11,12)
-- now try to add too many items to an array
guard
	addMany myArray otherArray 
catching
	boundedError: caught (print "Tried to add too many items" debug)
end
"Tried to add too many items"

An examination of myArray shows that we succeeded in adding the first ten items before the exception was reported.

myArray
#(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Like caught, the throw again expression causes ScriptX to stop checking the remaining statements in this catching clause. Unlike caught, the exception is then reported again, which causes ScriptX to test each of the exceptions in any surrounding guard constructs, or to drop the exception if there are no surrounding guard constructs. For example, if x is some number, and y is 0, the catching construct prints a message and then reports the divideByZero exception again, so any surrounding guard constructs can catch it if needed.

guard (z := x/y)
catching
divideByZero: (print "Divide By Zero"; throw again)
end

To throw again is to leave the exception uncaught. It is up to surrounding guard expressions to catch the exception. If there is no surrounding guard expression, or if the surrounding guard expression fails to catch the exception, the thread dies, and no value is returned.


This document is part of the ScriptX Language Guide, one of the volumes of the ScriptX Technical Reference Series. ScriptX is developed by the ScriptX Engineering Team at Apple Computer, successor to the Kaleida Engineering Team at Kaleida Labs, Inc.

Copyright 1996 Apple Computer, Inc. All Rights Reserved.